import { defineComponent, h } from "vue"
import { Layout } from "./types"
import { isString, cloneDeep } from 'lodash-es'
import { getComponent } from "."
import { ElSplitter, ElSplitterPanel } from "element-plus"

type SplitterPanelProps = {
  size?: string | number,
  min?: string | number,
  max?: string | number,
  resizable?: boolean,
  collapsible?: boolean
}

export default defineComponent({
  setup() {
    return () => h(render)
  }
})

/**
 * 渲染组件
 * @param props {layout: 组件的布局配置, props: 组件的属性}
 * @returns 
 */
function render(props: { layout: Layout, props?: Record<string, any> }) {
  const layout = cloneDeep(props.layout)
  const componentProps = props.props

  return renderLayout(layout, componentProps)
}

function renderLayout(layout: Layout, props: Record<string, any>) {
  const { type, cls, style, content, children } = layout
  const componentProps = { ...(layout.componentProps || {}), class: cls, style }
  const rawChildren = children ? children.map(child => renderLayout(child, props)) : content
  if(!type) {
    if(layout.component === 'split') {
      return renderSplitter(layout, props)
    } else {
      return h(layout.component || 'div', componentProps, {default: () => rawChildren})
    }
  }

  const name = layout.component || `Default`
  const component = getComponent(type, layout.component)
  if(!component) throw Error(`组件【${type}.${name}】不存在`)

  // 初始化布局配置里的componentProps,如果componentProps里的值是以【$】开头，表示是引用组件里的属性
  const layoutProps = layout.componentProps || {}
  for(const key in layoutProps) {
    const value = layoutProps[key]
    if(value && isString(value)) {
      const val = value as string
      if(val.startsWith('$')) layoutProps[key] = props ? props[val.substring(1)] : void 0
    }
  }
  return h(component, { ...props, ...layoutProps, class: cls, style }, {default: () => rawChildren})
}

function renderSplitter(layout: Layout, props: Record<string, any>) {
  const { children, content } = layout
  if(!children) return h(ElSplitter, content)
  
  const rawChildren = children.map(child => {
    const splitterPanelProps: SplitterPanelProps = {}
    if(child.componentProps) {
      const { size, min, max, resizable, collapsible } = child.componentProps
      if(size) {
        splitterPanelProps.size = size
        delete child.componentProps.size
      }
      if(min) {
        splitterPanelProps.min = min
        delete child.componentProps.min
      }
      if(max) {
        splitterPanelProps.max = max
        delete child.componentProps.max
      }
      if(resizable !== void 0) {
        splitterPanelProps.resizable = resizable
        delete child.componentProps.resizable
      }
      if(collapsible !== void 0) {
        splitterPanelProps.collapsible = collapsible
        delete child.componentProps.collapsible
      }
    }
    return h(ElSplitterPanel, splitterPanelProps, {default: () => renderLayout(child, props)})
  })

  const componentProps = layout.componentProps
  const splitterProps = componentProps?.layout ? {layout: componentProps.layout} : {}
  return h(ElSplitter, splitterProps, {default: () => rawChildren})
}
